package com.ruoyi.web.sso.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.WeekFields;
import java.util.*;

public class DateUtil {

    /**
     * 计算两个日期的相隔天数
     * @param d1
     * @param d2
     * @return
     */
    public static int getDaysBetween(Calendar d1, Calendar d2) {
        if (d1.after(d2)) {
            Calendar swap = d1;
            d1 = d2;
            d2 = swap;
        }
        int days = d2.get(Calendar.DAY_OF_YEAR) - d1.get(Calendar.DAY_OF_YEAR);
        int y2 = d2.get(Calendar.YEAR);
        if (d1.get(Calendar.YEAR) != y2) {
            d1 = (Calendar) d1.clone();
            do {
                days += d1.getActualMaximum(Calendar.DAY_OF_YEAR);
                d1.add(Calendar.YEAR, 1);
            } while (d1.get(Calendar.YEAR) != y2);
        }
        return days;
    }

    /**
     * 计算2个日期之间的工作日相隔天数
     * @param d1
     * @param d2
     * @return
     */
    public static int getWorkingDay(Calendar d1, Calendar d2) {
        int result = -1;
        if (d1.after(d2)) {
            Calendar swap = d1;
            d1 = d2;
            d2 = swap;
        }

        //开始日期的日期偏移量
        int charge_start_date = 0;
        //结束日期的日期偏移量
        int charge_end_date = 0;
        // 日期不在同一个日期内
        int stmp;
        int etmp;
        stmp = 7 - d1.get(Calendar.DAY_OF_WEEK);
        etmp = 7 - d2.get(Calendar.DAY_OF_WEEK);
        // 开始日期为星期六和星期日时偏移量为0
        if (stmp != 0 && stmp != 6) {
            charge_start_date = stmp - 1;
        }
        // 结束日期为星期六和星期日时偏移量为0
        if (etmp != 0 && etmp != 6) {
            charge_end_date = etmp - 1;
        }
        result = (getDaysBetween(getNextMonday(d1), getNextMonday(d2)) / 7)
                * 5 + charge_start_date - charge_end_date;
        return result + 1;
    }

    /**
     * 获得日期的下一个星期一的日期
     * @param date
     * @return
     */
    public static Calendar getNextMonday(Calendar date) {
        Calendar result = null;
        result = date;
        do {
            result = (Calendar) result.clone();
            result.add(Calendar.DATE, 1);
        } while (result.get(Calendar.DAY_OF_WEEK) != 2);
        return result;
    }

    public static Map<String,Integer> getWeekAndYear(String date) {
        Map<String,Integer> result =  new HashMap<>();
        Calendar cal = Calendar.getInstance();

//        --设置一周的开始,默认是周日,这里设置成星期一
        cal.setFirstDayOfWeek(Calendar.MONDAY);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat formatMon = new SimpleDateFormat("MM");
        SimpleDateFormat formatYear = new SimpleDateFormat("yyyy");
        Date d = null;
        try {
            d = format.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        cal.setTime(d);
        int month = Integer.valueOf(formatMon.format(d));
        int year = Integer.valueOf(formatYear.format(d));

        int week = cal.get(Calendar.WEEK_OF_YEAR);
        result.put("week", week);
        if(week == 1 && month == 12){
            result.put("year", year + 1);
        }else{

            result.put("year", year);
        }

        return result;
    }
    /**
     * 获取指定年-月(yyyy-mm)的工作日天数
     * @param year_month
     * @return
     */
    public static int getWorkingDayOfMonth(String year_month){
        int year = Integer.parseInt(year_month.substring(0,year_month.indexOf("-")));
        int month = Integer.parseInt(year_month.substring(year_month.indexOf("-") + 1));
        Calendar start = Calendar.getInstance();
        start.clear();
        start.set(Calendar.YEAR, year);
        start.set(Calendar.MONTH, month - 1);
        start.set(Calendar.DAY_OF_MONTH, 1);

        Calendar end = Calendar.getInstance();
        end.clear();
        end = (Calendar) start.clone();
        end.add(Calendar.MONTH,1);
        end.add(Calendar.DAY_OF_MONTH,-1);

        return getWorkingDay(start,end);
    }


    /**
     * 获取当前日期是星期几<br>
     *
     * @param date
     * @return 当前日期是星期几
     */
    public static String getWeekOfDate(Date date) {
        String[] weekDays = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0)
            w = 0;
        return weekDays[w];
    }
    /**
     * 获取当前日期是星期几<br>
     *
     * @param date
     * @return 当前日期是星期几
     */
    public static String getWeekNumberOfDate(Date date) {
        String[] weekDays = { "7", "1", "2", "3", "4", "5", "6" };
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0)
            w = 0;
        return weekDays[w];
    }

    /**
     * 根据开始时间
     * @param startTime
     * @param endTime
     * @return
     */
    public static List<String> getWeekList(LocalDate startTime, LocalDate endTime) {
        List<String> resultList = new ArrayList<String>();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy.MM.dd");

        //判断是否同一周
        WeekFields weekFields = WeekFields.of(DayOfWeek.MONDAY,4);
        if(startTime.get(weekFields.weekOfWeekBasedYear()) == endTime.get(weekFields.weekOfWeekBasedYear())){
            String v = df.format(startTime) +"-"+ df.format(endTime);
            resultList.add(v);
            return resultList;
        }

        //开始周
        TemporalAdjuster FIRST_OF_WEEK = TemporalAdjusters.ofDateAdjuster(localDate -> localDate.minusDays(localDate.getDayOfWeek().getValue() - DayOfWeek.MONDAY.getValue()));
        LocalDate startFirstWeek = startTime.with(FIRST_OF_WEEK);  //开始周开始日期
        TemporalAdjuster LAST_OF_WEEK = TemporalAdjusters.ofDateAdjuster(localDate -> localDate.plusDays(DayOfWeek.SUNDAY.getValue() - localDate.getDayOfWeek().getValue()));
        LocalDate endFirstWeek = startTime.with(LAST_OF_WEEK);     //开始周结束日期


        //结束周
        TemporalAdjuster FIRST_OF_WEEK1 = TemporalAdjusters.ofDateAdjuster(localDate -> localDate.minusDays(localDate.getDayOfWeek().getValue() - DayOfWeek.MONDAY.getValue()));
        LocalDate startLastWeek = endTime.with(FIRST_OF_WEEK1);
        TemporalAdjuster LAST_OF_WEEK1 = TemporalAdjusters.ofDateAdjuster(localDate -> localDate.plusDays(DayOfWeek.SUNDAY.getValue() - localDate.getDayOfWeek().getValue()));
        LocalDate endLastWeek = endTime.with(LAST_OF_WEEK1);

        //将第一周添加
        String v = df.format(startTime) +"-"+ df.format(endFirstWeek);
        resultList.add(v);

        while (true) {
            startFirstWeek = startFirstWeek.plusDays(7);
            if (startFirstWeek.with(LAST_OF_WEEK).equals(startLastWeek.with(LAST_OF_WEEK1))) {
                break;
            } else {
                String v1 = df.format(startFirstWeek.with(FIRST_OF_WEEK)) +"-"+ df.format(startFirstWeek.with(LAST_OF_WEEK));
                resultList.add(v1);
                //System.out.println("日期="+startFirstWeek+"开始周="+startFirstWeek.with(FIRST_OF_WEEK)+"结束周="+startFirstWeek.with(LAST_OF_WEEK));
            }
        }
        String v1 = df.format(startLastWeek)+"-"+ df.format(endTime);
        resultList.add(v1);
        return resultList;
    }
    public static String dateByYMDHMS(Date date){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return format.format(date);
    }
    public static String dateByYMD(Date date){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        return format.format(date);
    }
    public static String dateByYMD1(Date date){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-M-d");
        return format.format(date);
    }
    public static String dateByYM(Date date){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
        return format.format(date);
    }
    public static String dateByY(Date date){
        SimpleDateFormat format = new SimpleDateFormat("yyyy");
        return format.format(date);
    }
    public static String dateByM(Date date){
        SimpleDateFormat format = new SimpleDateFormat("M");
        return format.format(date);
    }

    public static String dateByHM(Date date){
        SimpleDateFormat format = new SimpleDateFormat("HH:mm");
        return format.format(date);
    }

    public static String dateStringByHMS(Date date){
        SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
        return format.format(date);
    }

    public static Date dateByHMS(Date date){
        SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
        try {
            return format.parse(format.format(date));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }


    public static Date stringByHMS(String date){
        SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
        try {
            return format.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return  new Date();
    }

    public static Date stringByYMD(String date){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return format.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return  new Date();
    }
    public static Date stringByYM(String date){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
        try {
            return format.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return  new Date();
    }


    public static Date newDateByYMD(){
        Date date  = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return format.parse(format.format(date));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    public static String  getStringTime(int day){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date date=new Date();
        date.setTime(Long.valueOf(date.getTime()- (day* 86400000)));
        return format.format(date);
    }

    public static Long  getDayTime(int day){
        Date date = DateUtil.newDateByYMD();
        return Long.valueOf(date.getTime()- (day* 86400000));
    }


    public static String getLastDayOfMonth(String yearMonth) {
        int year = Integer.parseInt(yearMonth.split("-")[0]);  //年
        int month = Integer.parseInt(yearMonth.split("-")[1]); //月
        Calendar cal = Calendar.getInstance();
        // 设置年份
        cal.set(Calendar.YEAR, year);
        // 设置月份
        // cal.set(Calendar.MONTH, month - 1);
        cal.set(Calendar.MONTH, month); //设置当前月的上一个月
        // 获取某月最大天数
        //int lastDay = cal.getActualMaximum(Calendar.DATE);
        int lastDay = cal.getMinimum(Calendar.DATE); //获取月份中的最小值，即第一天
        // 设置日历中月份的最大天数
        //cal.set(Calendar.DAY_OF_MONTH, lastDay);
        cal.set(Calendar.DAY_OF_MONTH, lastDay - 1); //上月的第一天减去1就是当月的最后一天
        // 格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(cal.getTime());
    }

    public static List<Date> getDates(int year,int month){
        List<Date> dates = new ArrayList<Date>();

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH,  month - 1);
        cal.set(Calendar.DATE, 1);
        while(cal.get(Calendar.YEAR) == year &&
                cal.get(Calendar.MONTH) < month){
            int day = cal.get(Calendar.DAY_OF_WEEK);

            if(!(day == Calendar.SUNDAY || day == Calendar.SATURDAY)){
                dates.add((Date)cal.getTime().clone());
            }
            cal.add(Calendar.DATE, 1);
        }
        return dates;
    }

    /**
     * 秒转换为指定格式的日期
     * @param second
     * @param patten
     * @return
     */
    public static String secondToDate(long second, String patten) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(second * 1000);//转换为毫秒
        Date date = calendar.getTime();
        SimpleDateFormat format = new SimpleDateFormat(patten);
        String dateString = format.format(date);
        return dateString;
    }
    /**
     * 获取指定年月的最后一天
     * @param year
     * @param month
     * @return
     */
    public static String getLastDayOfMonth(int year, int month) {
        Calendar cal = Calendar.getInstance();
        //设置年份
        cal.set(Calendar.YEAR, year);
        //设置月份
        cal.set(Calendar.MONTH, month-1);
        //获取某月最大天数
        int lastDay = cal.getActualMaximum(Calendar.DATE);
        //设置日历中月份的最大天数
        cal.set(Calendar.DAY_OF_MONTH, lastDay);
        //格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(cal.getTime());
    }

    public static String getLongByMYSHMS(Long time) {
        Date date = new Date();
        date.setTime(time);
        return dateByYMDHMS(date);
    }

    public static String getLongByHM(Long time) {
        Date date = new Date();
        date.setTime(time);
        return dateByHM(date);
    }
    public static String getLongByHMS(Long time) {
        Date date = new Date();
        date.setTime(time);
        return dateStringByHMS(date);
    }

    public static String getLongByYMD(Long time) {
        Date date = new Date();
        date.setTime(time);
        return dateByYMD(date);
    }

    public static Long getSurplusSecond(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
        try {
            Long y= format.parse(dateStringByHMS(new Date())).getTime()/1000;
            Long v = date.getTime()/1000;
            return v-y;
        } catch (ParseException e) {
            e.printStackTrace();
        }
       return Long.valueOf(0);
    }


    /**
     * Test
     * @param args
     */
    public static void main(String[] args) throws  Exception{
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdf1 = new SimpleDateFormat("dd");
        Date date =   sdf.parse("2021-1-31 17:30:00");

        Date date1 =   sdf.parse("2021-12-21 17:30:00");
        Calendar cale = Calendar.getInstance();
        cale.set(Calendar.DAY_OF_MONTH,0);//设置为1号,当前日期既为本月第一天
        String lastDay = sdf1.format(cale.getTime());

        System.out.println("===============last:"+birthdayMonthDay(date,date1));

    }
    public static final int betweenMonths(Date bigger, Date smaller) {
        if (bigger.compareTo(smaller) < 0)
            return 0;
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(bigger);
        c2.setTime(smaller);
        Integer year = c1.get(Calendar.YEAR) - c2.get(Calendar.YEAR);
        int month = c1.get(Calendar.MONTH) - c2.get(Calendar.MONTH);
        int days = c1.get(Calendar.DAY_OF_MONTH) - c2.get(Calendar.DAY_OF_MONTH);
        month += (year * 12);
        return days < 0 ? month - 1 : month;
    }

    public static String birthdayMonthDay(Date date,Date date1) {
        if (date.getTime()-date1.getTime()<0){
            return String.valueOf(0);
        }
        //月数
        int m = DateUtil.betweenMonths(date,date1);

        SimpleDateFormat sdf1 = new SimpleDateFormat("dd");
        int d = Integer.parseInt(sdf1.format(date1))-Integer.parseInt(sdf1.format(date));
        if (d>0){
            return m+"M"+d+"D";
        }else {
            Calendar cale = Calendar.getInstance();
            cale.set(Calendar.DAY_OF_MONTH,0);//设置为1号,当前日期既为本月第一天
            //上个月多少天
            String day = sdf1.format(cale.getTime());
            Integer v = Integer.parseInt(day)+d;
            m = m-1;
            return m+"M"+v+"D";
        }
    }


    public static final String toNormalString(Date date) {
        return millisToDateTime(date.getTime(), "yyyy-MM-dd");
    }

    public static final String millisToDateTime(Long millis, String pattern) {
        LocalDateTime time = Instant.ofEpochMilli(millis).atZone(ZoneId.systemDefault()).toLocalDateTime();
        return time.format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 获取出生到现在多少天
     *
     * @param date  当前日期
     * @param date1 生日
     * @return
     */
    public static int birthdayDay(Date date, Date date1) {
        long betweenDays = (date.getTime() - date1.getTime()) / (1000L*3600L*24L);
        return (int) Math.abs(betweenDays);
    }
}
